package com.yehui.alibaba;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import io.seata.common.loader.LoadLevel;
import io.seata.rm.datasource.undo.parser.JacksonUndoLogParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

/**
 * 为了解决无法序列化 LocalDateTime 的情况
 *
 * https://github.com/seata/seata/issues/3620
 *
 * @author 业徽
 * @date 2021/8/4
 */
@LoadLevel(name = "custom")
public class CustomUndoLogParser extends JacksonUndoLogParser {

    private static final Logger logger = LoggerFactory.getLogger(CustomUndoLogParser.class);

    @Override
    public void init() {
        super.init();
        logger.info("初始化 undolog 解析器");
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
        try {
            final Field mapper = JacksonUndoLogParser.class.getDeclaredField("mapper");
            mapper.setAccessible(true);
            final ObjectMapper objectMapper = (ObjectMapper)mapper.get(this);
            objectMapper.registerModule(javaTimeModule);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            logger.error("配置 mapper 失败. ", e);
            throw new RuntimeException(e);
        }
    }

    @Override
    public String getName() {
        return "custom";
    }
}
